package api

import (
	"getaway/basic/config"
	driver "getaway/basic/proto/driverproto"
	"getaway/handler/request"
	"getaway/handler/response"
	"getaway/middleware"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	"time"
)

// CreateDriver
// @Summary      创建司机
// @Description  创建司机
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver   body    request.DriverCreate    true  "用户参数"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/createDriver [post]
func CreateDriver(c *gin.Context) {
	var req request.DriverCreate
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.DriverCreate(c, &driver.DriverCreateReq{
		UserId:             req.UserId,
		CityId:             req.CityId,
		ManagerId:          req.ManagerId,
		Name:               req.Name,
		IdCard:             req.IdCard,
		Mobile:             req.Mobile,
		Sex:                req.Sex,
		ContractStartTigme: req.ContractStartTime,
		ContractEndTime:    req.ContractEndTime,
	})
	if err != nil {
		response.SrvError(c, "服务器错误", err.Error())
		return
	}

	// 记录创建司机行为
	userId, _ := c.Get("userId")
	middleware.RecordClickBehavior(c, userId, "创建司机", map[string]interface{}{
		"userId":  req.UserId,
		"name":    req.Name,
		"mobile":  req.Mobile,
		"success": err == nil,
	})

	response.Success(c, "创建司机成功", create)
}

// DriverRevenue
// @Summary      司机营业额
// @Description  查询司机在时间范围内的营业额（支持按日/按月）
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver_id   query   int     true  "司机ID"
// @Param        start_date  query   string  true  "开始日期 YYYY-MM-DD 或 YYYY-MM"
// @Param        end_date    query   string  true  "结束日期 YYYY-MM-DD 或 YYYY-MM"
// @Param        type        query   int     true  "统计类型 1:日 2:月"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/driverRevenue [get]
func DriverRevenue(c *gin.Context) {
    var req request.DriverRevenue
    if err := c.ShouldBindQuery(&req); err != nil {
        response.ParameterError(c, "参数错误", err.Error())
        return
    }
    // 透传到 driver 服务
    resp, err := config.DriverClient.DriverRevenue(c, &driver.DriverRevenueReq{
        DriverId:  req.DriverId,
        StartDate: req.StartDate,
        EndDate:   req.EndDate,
        Type:      req.Type,
    })
    if err != nil {
        response.SrvError(c, "服务器错误", err.Error())
        return
    }
    response.Success(c, "查询成功", resp)
}

// DriverCarpoolAddressList
// @Summary      司机顺风车地址列表
// @Description  根据司机ID返回顺风车地址列表
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver_id   query   int     true  "司机ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/carpoolAddressList [get]
func DriverCarpoolAddressList(c *gin.Context) {
    var req request.DriverCarpoolAddressList
    if err := c.ShouldBindQuery(&req); err != nil {
        response.ParameterError(c, "参数错误", err.Error())
        return
    }
    resp, err := config.DriverClient.DriverCarpoolAddressList(c, &driver.DriverCarpoolAddressListReq{
        DriverId: req.DriverId,
    })
    if err != nil {
        response.SrvError(c, "服务器错误", err.Error())
        return
    }
    response.Success(c, "查询成功", resp)
}

// UpdateDriver
// @Summary      更新司机信息
// @Description  更新司机信息
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver   body    request.DriverUpdate    true  "用户参数"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/updateDriver [post]
func UpdateDriver(c *gin.Context) {
	var req request.DriverUpdate
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.DriverUpdate(c, &driver.DriverUpdateReq{
		Id:                               req.Id,
		MobileCarriers:                   req.MobileCarriers,
		CompanyLogoImg:                   req.CompanyLogoImg,
		RegistrationDistrictCode:         req.RegistrationDistrictCode,
		DriverBirthday:                   req.DriverBirthday,
		Nationality:                      req.Nationality,
		DriverNation:                     req.DriverNation,
		DriverLicenseNumber:              req.DriverLicenseNumber,
		MaritalStatus:                    req.MaritalStatus,
		ForeignLanguageAbility:           req.ForeignLanguageAbility,
		AppVersion:                       req.AppVersion,
		MapType:                          req.MapType,
		Education:                        req.Education,
		HouseholdRegistrationAuthority:   req.HouseholdRegistrationAuthority,
		PermanentAddress:                 req.PermanentAddress,
		CommunicationAddress:             req.CommunicationAddress,
		DriverPhotoFileNumber:            req.DriverPhotoFileNumber,
		DriverLicense:                    req.DriverLicense,
		ScanOfMotorVehicleDrivingLicense: req.ScanOfMotorVehicleDrivingLicense,
		PermittedVehicleType:             req.PermittedVehicleType,
		FirstDrivingLicense:              req.FirstDrivingLicense,
		DriverLicenseStart:               req.DriverLicenseStart,
		DriverLicenseEnd:                 req.DriverLicenseEnd,
		IsTourTaxiDriver:                 req.IsTourTaxiDriver,
		OnlineTaxiLicenseNumber:          req.OnlineTaxiLicenseNumber,
		OnlineTaxiLicenseIssuer:          req.OnlineTaxiLicenseIssuer,
		LicenseIssueDate:                 req.LicenseIssueDate,
		FirstLicenseIssueDate:            req.FirstLicenseIssueDate,
		LicenseValidStart:                req.LicenseValidStart,
		LicenseValidEnd:                  req.LicenseValidEnd,
		EquipmentDate:                    req.EquipmentDate,
		IsFullTimeDriver:                 req.IsFullTimeDriver,
		IsInBlacklist:                    req.IsInBlacklist,
		ServiceType:                      req.ServiceType,
		ContractSignCompany:              req.ContractSignCompany,
		EmergencyContact:                 req.EmergencyContact,
		EmergencyContactMobile:           req.EmergencyContactMobile,
		EmergencyContactAddress:          req.EmergencyContactAddress,
	})
	if err != nil {
		response.ParameterError(c, "修改司机失败", err.Error())
		return
	}

	// 记录更新司机信息行为
	userId, _ := c.Get("userId")
	middleware.RecordClickBehavior(c, userId, "更新司机信息", map[string]interface{}{
		"driverId": req.Id,
		"success":  err == nil,
	})

	response.Success(c, "修改司机成功", create)

}

// VehicleBind
// @Summary      更新司机信息
// @Description  更新司机信息
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver   body    request.VehicleBind    true  "用户参数"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/bindVehicle [post]
func VehicleBind(c *gin.Context) {
	var req request.VehicleBind
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.VehicleBind(c, &driver.VehicleBindReq{
		DriverId:  int64(req.DriverId),
		VehicleId: int64(req.VehicleId),
		BindType:  int32(req.BindType),
	})
	if err != nil {
		response.ParameterError(c, "车辆绑定失败", err.Error())
		return
	}

	// 记录车辆绑定行为
	userId, _ := c.Get("userId")
	middleware.RecordClickBehavior(c, userId, "车辆绑定", map[string]interface{}{
		"driverId":  req.DriverId,
		"vehicleId": req.VehicleId,
		"bindType":  req.BindType,
		"success":   err == nil,
	})

	response.Success(c, "车辆绑定成功", create)
}

// DriverIdImgCreate
// @Summary      创建司机身份证图片
// @Description  创建司机身份证图片
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver   body    request.DriverIdImgCreate    true  "用户参数"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/bindVehicle [post]
func DriverIdImgCreate(c *gin.Context) {
	var req request.DriverIdImgCreate
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.DriverIdImgCreate(c, &driver.DriverIdImgCreateReq{
		DriverId:                             req.DriverId,
		PersonalAvatar:                       req.PersonalAvatar,
		IdCardFront:                          req.IdCardFront,
		IdCardBack:                           req.IdCardBack,
		HeadIdCardBack:                       req.HeadIdCardBack,
		DriverLicenseFrout:                   req.DriverLicenseFrout,
		ProfessionalQualificationCertificate: req.ProfessionalQualificationCertificate,
		Others:                               req.Others,
	})
	if err != nil {
		response.ParameterError(c, "司机身份证图片创建失败", err.Error())
		return
	}

	// 记录司机身份证图片创建行为
	userId, _ := c.Get("userId")
	middleware.RecordClickBehavior(c, userId, "司机身份证图片创建", map[string]interface{}{
		"driverId": req.DriverId,
		"success":  err == nil,
	})

	response.Success(c, "司机身份证图片创建成功", create)
}

// DriverTrainingCourseCreate
// @Summary      司机培训课程创建
// @Description  司机培训课程创建
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver   body    request.DriverTrainingCourseCreate    true  "用户参数"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/driverTrainingCourseCreate [post]
func DriverTrainingCourseCreate(c *gin.Context) {
	var req request.DriverTrainingCourseCreate
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.DriverTrainingCourseCreate(c, &driver.DriverTrainingCourseCreateReq{
		DriverId:   req.DriverId,
		CourseName: req.CourseName,
		CourseDate: req.CourseDate,
		StartDate:  req.StartDate,
		EndDate:    req.EndDate,
		Duration:   req.Duration,
	})
	if err != nil {
		response.ParameterError(c, "司机培训课程创建失败", err.Error())
		return
	}

	// 记录司机培训课程创建行为
	userId, _ := c.Get("userId")
	middleware.RecordClickBehavior(c, userId, "司机培训课程创建", map[string]interface{}{
		"driverId":   req.DriverId,
		"courseName": req.CourseName,
		"success":    err == nil,
	})

	response.Success(c, "司机培训课程创建成功", create)
}

// BankAccountCreate
// @Summary      司机银行账号创建
// @Description  司机银行账号创建
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver   body    request.BankAccountCreate    true  "用户参数"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/bankAccountCreate [post]
func BankAccountCreate(c *gin.Context) {
	var req request.BankAccountCreate
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.BankAccountCreate(c, &driver.BankAccountCreateReq{
		DriverId:       req.DriverId,
		BankName:       req.BankName,
		BankCardNumber: req.BankCardNumber,
	})
	if err != nil {
		response.ParameterError(c, "司机银行账号创建失败", err.Error())
		return
	}

	// 记录司机银行账号创建行为
	userId, _ := c.Get("userId")
	middleware.RecordClickBehavior(c, userId, "司机银行账号创建", map[string]interface{}{
		"driverId": req.DriverId,
		"bankName": req.BankName,
		"success":  err == nil,
	})

	response.Success(c, "司机银行账号创建成功", create)
}

// DriverList
// @Summary      司机列表
// @Description  司机列表
// @Tags         司机模块
// @Accept       json
// @Produce      json
// @Param        driver   query    request.DriverList    true  "用户参数"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.Response
// @Failure      500  {object}  response.Response
// @Router       /driver/driverList [get]
func DriverList(c *gin.Context) {
	var req request.DriverList
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.DriverList(c, &driver.DriverListReq{
		DriverId: int64(req.DriverId),
	})
	if err != nil {
		response.ParameterError(c, "司机列表失败", err.Error())
		return
	}

	// 记录司机列表查询行为
	userId, _ := c.Get("userId")
	middleware.RecordClickBehavior(c, userId, "司机列表查询", map[string]interface{}{
		"driverId": req.DriverId,
		"success":  err == nil,
	})

	response.Success(c, "司机列表成功", create)
}
func DriverLists(c *gin.Context) {
	var req request.DriverLists
	// 根据 Content-Type Header 推断使用哪个绑定器。
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	create, err := config.DriverClient.DriverLists(c, &driver.DriverListsReq{
		Page:     req.Page,
		PageSize: req.PageSize,
	})
	if err != nil {
		response.ParameterError(c, "获取所有司机信息列表失败", err.Error())
		return
	}
	response.Success(c, "获取所有司机信息列表成功", create)
}

// DriverLoc 司机位置
func DriverLoc(c *gin.Context) {
	var req request.DriverLoc
	if err := c.ShouldBind(&req); err != nil {
		response.ParameterError(c, "参数错误", err.Error())
		return
	}
	if config.Rdb == nil {
		response.SrvError(c, "服务端错误", "redis not ready")
		return
	}
	// GEO 写入
	key := "geo:drivers:" + itoa(req.CityId)
	_, err := config.Rdb.GeoAdd(config.Ctx, key, &redis.GeoLocation{Name: itoa(req.DriverId), Longitude: req.Lng, Latitude: req.Lat}).Result()
	if err != nil {
		response.SrvError(c, "服务端错误", err.Error())
		return
	}
	// 推送至司机位置流
	stream := "stream:driver:loc:" + itoa(req.DriverId)
	_ = config.Rdb.XAdd(config.Ctx, &redis.XAddArgs{Stream: stream, Values: map[string]interface{}{"lat": req.Lat, "lng": req.Lng, "ts": nowUnix()}}).Err()
	response.Success(c, "ok", nil)
}

// itoa 将 uint32 转换为字符串
func itoa(u uint32) string {
	if u == 0 {
		return "0"
	}
	b := make([]byte, 0, 10)
	for u > 0 {
		b = append(b, byte('0'+u%10))
		u /= 10
	}
	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
		b[i], b[j] = b[j], b[i]
	}
	return string(b)
}

// nowUnix 返回当前时间的 Unix 时间戳
func nowUnix() int64 { return time.Now().Unix() }
